
#include "testSSHClient.h"
#include "../utils/Prompt.h"
#include "../ssh/SecurityTokenInteractive.h"
#include "../ssh/SecurityTokenPassword.h"
#include "../ssh/SecurityChain.h"
#include "../ssh/SSHClient.h"
#include "../ssh/ShellChannel.h"
#include "../ssh/SCPSendChannel.h"
#include "../ssh/SCPReceiveChannel.h"
#include "../ssh/PersistentForwardChannel.h"
#include "../ssh/RemoteSSHKeyFile.h"

void tests::testSSHClientBasic(const char *hostname, int portno, apr_pool_t *mp)
{
   // Create a basic security token
   Prompt prmpt_username(NULL);
   Prompt prmpt_password(NULL);
   char *username_got = prmpt_username.promptNormal("Username: ");
   char *password_got = prmpt_password.promptPassword("Password: ");
   SecurityTokenInteractive *secur_tok1 = new SecurityTokenInteractive(password_got);
   SecurityChain *secur_chain = new SecurityChain();
   secur_chain->addSecurityToken(secur_tok1);
   SSHClient *sshcli = new SSHClient(hostname, portno, mp, NULL, 0, hostname, portno, NULL);
   sshcli->useSecurityChain(secur_chain, username_got);
   ShellChannel *shell_channel = new ShellChannel(*sshcli);
   APRFuture<char *> *data = shell_channel->runCommandToStringFuture("ls");
   printf("command returned: %s\n", *(data->get()));
   free(*(data->get()));
   delete data;
   delete shell_channel;
   delete sshcli;
   delete secur_chain;
}

void tests::testSSHClientSCPBuffers(const char *hostname, int portno, apr_pool_t *mp)
{
   // Create a basic security token
   Prompt prmpt_username(NULL);
   Prompt prmpt_password(NULL);
   char *username_got = prmpt_username.promptNormal("Username: ");
   char *password_got = prmpt_password.promptPassword("Password: ");
   SecurityTokenInteractive *secur_tok1 = new SecurityTokenInteractive(password_got);
   SecurityChain *secur_chain = new SecurityChain();
   secur_chain->addSecurityToken(secur_tok1);
   SSHClient *sshcli = new SSHClient(hostname, portno, mp, NULL, 0, hostname, portno, NULL);
   sshcli->useSecurityChain(secur_chain, username_got);
   const char buffer[] = "buffer that is full of words which are in turn helpful to test the secure copying code as long as they are quite verbose";
   SCPSendChannel *scp_send_channel = new SCPSendChannel(*sshcli);
   APRFuture<int> *future_result = scp_send_channel->copyBufferToRemoteFileFuture("remote_local_test_file_acquire", buffer, strlen(buffer), 0644);
   int success_ret = *(future_result->get());
   printf("copy buffer to remote file: %s\n", (success_ret == 0) ? "success" : "failure");
   delete scp_send_channel;
   delete future_result;
   ShellChannel *shell_channel = new ShellChannel(*sshcli);
   APRFuture<char *> *data = shell_channel->runCommandToStringFuture("cat remote_local_test_file_acquire");
   printf("command returned: %s\n", *(data->get()));
   printf("cat remote file: %s\n", (strcmp(*(data->get()), buffer) == 0) ? "success" : "failure");
   free(*(data->get()));
   delete data;
   SCPReceiveChannel *scp_recv_channel = new SCPReceiveChannel(*sshcli);
   int64_t newbuflen = 0;
   APRFuture<char *> *recv_future_result = scp_recv_channel->getBufferFromRemoteFileFuture("remote_local_test_file_acquire", &newbuflen, 0644);
   char *result_buffer = *(recv_future_result->get());
   printf("buffer returned: %s (length %" APR_INT64_T_FMT ")\n", result_buffer, newbuflen);
   printf("get buffer from remote file: %s\n", (strcmp(result_buffer, buffer) == 0) ? "success" : "failure");
   free(result_buffer);
   delete recv_future_result;
   delete scp_recv_channel;
   data = shell_channel->runCommandToStringFuture("rm remote_local_test_file_acquire");
   printf("command returned: %s\n", *(data->get()));
   free(*(data->get()));
   delete data;
   delete shell_channel;
   delete sshcli;
   delete secur_chain;
}

void tests::testSSHClientSCPFiles(const char *hostname, int portno, apr_pool_t *mp)
{
   // Create a basic security token
   Prompt prmpt_username(NULL);
   Prompt prmpt_password(NULL);
   char *username_got = prmpt_username.promptNormal("Username: ");
   char *password_got = prmpt_password.promptPassword("Password: ");
   SecurityTokenInteractive *secur_tok1 = new SecurityTokenInteractive(password_got);
   SecurityChain *secur_chain = new SecurityChain();
   secur_chain->addSecurityToken(secur_tok1);
   SSHClient *sshcli = new SSHClient(hostname, portno, mp, NULL, 0, hostname, portno, NULL);
   sshcli->useSecurityChain(secur_chain, username_got);
   const char buffer[] = "buffer that is full of words which are in turn helpful to test the secure copying code as long as they are quite verbose";
   SCPSendChannel *scp_send_channel = new SCPSendChannel(*sshcli);
   APRFuture<int> *future_result = scp_send_channel->copyBufferToRemoteFileFuture("remote_local_test_file_acquire", buffer, strlen(buffer), 0644);
   int success_ret = *(future_result->get());
   printf("copy buffer to remote file: %s\n", (success_ret == 0) ? "success" : "failure");
   delete future_result;
   delete scp_send_channel;
   ShellChannel *shell_channel = new ShellChannel(*sshcli);
   APRFuture<char *> *data = shell_channel->runCommandToStringFuture("cat remote_local_test_file_acquire");
   printf("command returned: %s\n", *(data->get()));
   printf("cat remote file: %s\n", (strcmp(*(data->get()), buffer) == 0) ? "success" : "failure");
   free(*(data->get()));
   delete data;
   SCPReceiveChannel *scp_recv_channel = new SCPReceiveChannel(*sshcli);
   int64_t newbuflen = 0;
   APRFuture<int> *recv_future_result = scp_recv_channel->getFileFromRemoteFileFuture("remote_local_test_file_acquire", "local_test_file_acquire", 0644);
   int result_value = *(recv_future_result->get());
   printf("get file from remote file: %s\n", (result_value == 0) ? "success" : "failure");
   delete recv_future_result;
   delete scp_recv_channel;
   data = shell_channel->runCommandToStringFuture("rm remote_local_test_file_acquire");
   printf("command returned: %s\n", *(data->get()));
   free(*(data->get()));
   delete data;
   SCPSendChannel *scp_send_channel2 = new SCPSendChannel(*sshcli);
   APRFuture<int> *future_result2 = scp_send_channel2->copyFileToRemoteFileFuture("remote_local_test_file_acquire", "local_test_file_acquire", 0644);
   int result_value2 = *(future_result2->get());
   printf("put file to remote file: %s\n", (result_value2 == 0) ? "success" : "failure");
   delete future_result2;
   delete scp_send_channel2;
   data = shell_channel->runCommandToStringFuture("cat remote_local_test_file_acquire");
   printf("command returned: %s\n", *(data->get()));
   printf("cat remote file: %s\n", (strcmp(*(data->get()), buffer) == 0) ? "success" : "failure");
   free(*(data->get()));
   delete data;
   data = shell_channel->runCommandToStringFuture("rm remote_local_test_file_acquire");
   printf("command returned: %s\n", *(data->get()));
   free(*(data->get()));
   delete data;
   delete shell_channel;
   delete sshcli;
   delete secur_chain;
}

void tests::testSSHClientForwarding(const char *hostname, int portno, apr_pool_t *mp)
{
   // Create a basic security token
   Prompt prmpt_username(NULL);
   Prompt prmpt_password(NULL);
   char *username_got = prmpt_username.promptNormal("Username: ");
   char *password_got = prmpt_password.promptPassword("Password: ");
   SecurityTokenInteractive *secur_tok1 = new SecurityTokenInteractive(password_got);
   SecurityChain *secur_chain = new SecurityChain();
   secur_chain->addSecurityToken(secur_tok1);
   SSHClient *sshcli = new SSHClient(hostname, portno, mp, NULL, 0, hostname, portno, NULL);
   sshcli->useSecurityChain(secur_chain, username_got);
   Prompt prmpt2_newhostname(NULL);
   Prompt prmpt2_newhostport(NULL);
   Prompt prmpt2_username(NULL);
   Prompt prmpt2_password(NULL);
   char *newhostname = prmpt2_newhostname.promptNormal("Next host: ");
   char *newhostport = prmpt2_newhostport.promptNormal("Next port: ");
   char *h2username = prmpt2_username.promptNormal("Username: ");
   char *h2password = prmpt2_password.promptPassword("Password: ");
   PersistentForwardChannel *pfc = new PersistentForwardChannel(*sshcli, 4, 32900, 33000,
      "127.0.0.1", atoi(newhostport), newhostname);
   SecurityTokenPassword *secur_tok3 = new SecurityTokenPassword(h2password);
   SecurityTokenInteractive *secur_tok2 = new SecurityTokenInteractive(h2password);
   SecurityChain *secur_chain2 = new SecurityChain();
   secur_chain2->addSecurityToken(secur_tok2);
   secur_chain2->addSecurityToken(secur_tok3);
   SSHClient *sshcli2 = new SSHClient("127.0.0.1", pfc->getLocalListenPort(), mp, NULL, 0,
      newhostname, atoi(newhostport), NULL);
   sshcli2->useSecurityChain(secur_chain2, h2username);
   ShellChannel *shell_channel = new ShellChannel(*sshcli2);
   APRFuture<char *> *data = shell_channel->runCommandToStringFuture("ls");
   printf("command returned: %s\n", *(data->get()));
   free(*(data->get()));
   delete data;
   delete shell_channel;
   delete sshcli2;
   delete secur_chain2;
   delete pfc;
   delete sshcli;
   delete secur_chain;
}
